package ui;

import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.nio.FloatBuffer;
import java.util.ArrayList;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;

import org.lwjgl.LWJGLException;

import primatives.PointND;

import tools.PointCloudViewer;
import triangulation.SimpleTriangulation;
import util.DataGenerator;
import util.PointCloudReader;
import util.PointCloudWriter;


public class Window_ViewerApp extends JFrame
{
	final JFileChooser fc = new JFileChooser();
	
//	public ViewerCanvas canvas;
	public ViewerCanvas canvas;
	public JMenuBar menu_bar;
	public JMenu menu_file;
	public JMenu menu_clustering;
	public JMenu menu_option;

	public Window_ViewerApp(String s, int w, int h) throws LWJGLException
	{
		setTitle(s);
		setSize(w, h);
		setLayout(new BorderLayout(5, 5));

		// setup OpenGL canvas
		add(canvas = new ViewerCanvas(), BorderLayout.CENTER);
		
		addWindowStateListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.out.println("Closing...");
				dispose();
				System.exit(0);
			}
		});
		
		// zooming in and out
		canvas.addMouseWheelListener(new MouseWheelListener()
		{
			@Override
			public void mouseWheelMoved(MouseWheelEvent e)
			{
//				getPreciseWheelRotation not avaiable in Java6 openjdk
				double delta = e.getWheelRotation();
				if (delta != 0)
				{
					double zoomAmount = delta/UIConst.MOUSE_WHEEL_SENSITIVITY;
					canvas.viewer.zoom((float)zoomAmount);
				}
			}
		});
		
		canvas.addKeyListener(new KeyListener() {
			
			@Override
			public void keyTyped(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void keyReleased(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void keyPressed(KeyEvent e)
			{
					
				canvas.move_mesh(e);
			}
		});
		
		setupGUI();
		
		setResizable(false);
		setVisible(true);
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
	}
	
	public void setupGUI()
	{
		JMenuItem fileOpen = new JMenuItem("Open");
		fileOpen.addActionListener(new ActionListener()
		{
	        public void actionPerformed(ActionEvent e)
	        {
                int returnVal = fc.showOpenDialog(Window_ViewerApp.this);

                if (returnVal == JFileChooser.APPROVE_OPTION)
                {
                    File file = fc.getSelectedFile();
                    ArrayList<PointND> pointCloud = PointCloudReader.ReadFile(file.getAbsolutePath());
                    
                    canvas.viewer.setPoints(pointCloud);

                    setTitle("Point Cloud Viewer - " + file.getAbsolutePath());
                }
	        }
		});
		
		JMenuItem fileClose = new JMenuItem("Exit");
		fileClose.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event)  { System.exit(0); } });
		
		JMenuItem exportImage = new JMenuItem("... as Image");
		exportImage.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				// TODO: file filters for images
                int returnVal = fc.showSaveDialog(Window_ViewerApp.this);

                if (returnVal == JFileChooser.APPROVE_OPTION)
                {
                	File file = fc.getSelectedFile();
                	canvas.takeScreenshot(file);
                }
			}
		});
		
		JMenu export = new JMenu("Export Mesh");
		export.add(exportImage);
		
		menu_file = new JMenu("File");
		menu_file.add(fileOpen);
		menu_file.add(export);
		menu_file.add(new JSeparator());
		menu_file.add(fileClose);
		
		
		JMenuItem cylinder_clustering = new JMenuItem("Cylinder Clustering");
		cylinder_clustering.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				// open the cylinder clustering frame
				CylinderClusteringFrame clusteringframe = new CylinderClusteringFrame(Window_ViewerApp.this);
			}
		});
		
		JMenuItem mst_clustering = new JMenuItem("MST Clustering");
		mst_clustering.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				MSTClusteringFrame mst_frame= new MSTClusteringFrame(Window_ViewerApp.this);
			}
		});
		
		
		menu_clustering = new JMenu("Clustering");
		menu_clustering.add(cylinder_clustering);
		menu_clustering.add(mst_clustering);
		
		menu_bar = new JMenuBar();
		menu_bar.add(menu_file);
		menu_bar.add(menu_clustering);
		setJMenuBar(menu_bar);
	}
	
	// testing code
	public static void main(String[] args) throws LWJGLException
	{
		Window_ViewerApp frame = new Window_ViewerApp("Point Cloud Viewer", UIConst.APP_WIDTH, UIConst.APP_HEIGHT);
//		ArrayList<PointND> p = DataGenerator.generateSemiFlat(25, 25, -500, 5);
//		ArrayList<PointND> p = DataGenerator.generatePerfectFlat(100, 100, -500);
//		ArrayList<PointND> p = DataGenerator.generatePerfectFlat(25, 25, -500);
		ArrayList<PointND> p = DataGenerator.generateBedding(6, 100, 10, 20, 1, 10, -500, -499);
		
//		ArrayList<PointND> p = DataGenerator.generateHalfCylinder(100, 100, 0.01);
//		ArrayList<PointND> p = DataGenerator.generateCone(50, 50, 36);
		
		
		

//		String voxelFilePath = "data"+File.separator+"scan_center_1to1_fill"+PointCloudReader.VOXEL_FILE_EXT;
//		ArrayList<PointND> pointCloud = PointCloudReader.ReadFile(voxelFilePath);
		ArrayList<PointND> pointCloud;

		pointCloud = p;
		
//		frame.canvas.triangulation = new SimpleTriangulation();
//		frame.canvas.triangulation.triangulate(pointCloud);
		
		frame.canvas.viewer = new PointCloudViewer();
		frame.canvas.viewer.setPoints(pointCloud);
	}
}
